package com.congee02.modelshellmvn.aop;


import com.congee02.modelshellmvn.anno.NeedPermission;
import com.congee02.modelshellmvn.entity.account.Account;
import com.congee02.modelshellmvn.exception.PermissionDeniedException;
import com.congee02.modelshellmvn.manager.auth.AuthManager;
import com.congee02.modelshellmvn.manager.token.AccountJwtValidator;
import com.congee02.modelshellmvn.utils.AnnotationUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class PermissionCheckAspect {

    @Resource
    private HttpServletRequest request;

    @Resource
    private AuthManager authManager;

    @Resource
    private AccountJwtValidator validator;

    @Pointcut("@annotation(com.congee02.modelshellmvn.anno.NeedPermission)")
    public void needPermissionAnnotatedMethod() {}

    private String jwt() {
        return request.getHeader("Authorization");
    }

    @Before("needPermissionAnnotatedMethod()")
    public void checkPermissionBeforeExecution(JoinPoint joinPoint) {
        Account account = validator.tryExtractInfo(
                new Account().setJwt(
                        jwt()
                )
        );
        log.info("Session Account: {}", account);
        NeedPermission needPermission = AnnotationUtils.extractAnnotationFromJoinPoint(
                joinPoint, NeedPermission.class
        );;
        boolean canOperate = authManager.canOperate(account, needPermission.value());
        log.info("Permission Check, NeedPermission: {}, Account: {}", needPermission.value(), account);
        if (! canOperate) {
            log.warn("Permission check failed");
            throw new PermissionDeniedException();
        }
        log.info("Permission check ok");
    }

}
